#include "can_ota.h"
#include "bsp_can.h"
#include "ota.h"
#include "log.h"
#include <string.h>
#include "bsp_delay.h"

// 全局变量
static struct {
    uint32_t total_size;     // 固件总大小
    uint32_t received_size;  // 已接收大小
    uint16_t current_index;  // 当前数据包索引
    uint8_t  is_updating;    // 是否在升级中
    uint8_t  device_id;      // 设备ID
    uint8_t  group_id;       // 组ID
    uint8_t  is_master;      // 是否为主设备
} can_ota_ctx = {0};

// 数据块传输相关
static struct {
    uint16_t block_size;                   // 数据块大小
    uint16_t packet_count;                 // 数据包数量
    uint16_t received_count;               // 已接收包数量
    uint8_t  is_receiving_block;           // 是否正在接收数据块
    uint8_t  block_buffer[MAX_BLOCK_SIZE]; // 数据块缓冲区
    uint32_t block_offset;                 // 数据块缓冲区偏移
} block_transfer = {0};

/**
 * @brief  初始化Flash缓冲区
 */
static void Init_Flash_Buffers(void)
{
    block_transfer.block_offset = 0;
    block_transfer.is_receiving_block = 0;
}

/**
 * @brief  发送CAN OTA响应
 */
uint8_t CAN_OTA_SendResponse(uint16_t index, uint8_t status)
{
    CAN_OTA_Response resp = {0};
    resp.index = index;
    resp.status = status;
    
    return BSP_CAN_Transmit(GET_RESP_ID(can_ota_ctx.device_id), 
                           (uint8_t*)&resp, sizeof(resp));
}

/**
 * @brief  处理开始命令
 */
static void Handle_Start_Command(CAN_OTA_Cmd *cmd)
{
    LOGI("Received OTA start command\r\n");
    
    // 初始化升级环境
    can_ota_ctx.total_size = cmd->param;
    can_ota_ctx.received_size = 0;
    can_ota_ctx.current_index = 0;
    can_ota_ctx.is_updating = 1;
    
    // 根据运行模式发送不同的响应
    if(OTA_GetRunMode() == RUN_MODE_BOOT) {
        LOGI("Boot mode, erasing application area...\r\n");
        // 初始化Flash并擦除应用程序区域
        if(OTA_Init() != OTA_OK) {
            LOGE("Failed to initialize OTA!\r\n");
            CAN_OTA_SendResponse(0, CAN_OTA_RESP_ERROR);
            return;
        }
        if(Erase_App_Area(can_ota_ctx.total_size) != OTA_OK) {
            LOGE("Failed to erase application area!\r\n");
            CAN_OTA_SendResponse(0, CAN_OTA_RESP_ERROR);
            return;
        }
        // 初始化Flash缓冲区
        Init_Flash_Buffers();
        LOGI("Boot mode, sending READY response\r\n");
        CAN_OTA_SendResponse(0, CAN_OTA_RESP_READY);
    } else {
        LOGI("App mode, sending OK response\r\n");
        // 应用程序模式下，设置升级标志并准备重启
        OTA_SetUpgradeFlag();
        CAN_OTA_SendResponse(0, CAN_OTA_RESP_OK);
        SysTick_Delay_Ms(100);  // 等待响应发送完成
        NVIC_SystemReset();
    }
}

/**
 * @brief  处理数据块开始命令
 */
static void Handle_Block_Start_Command(CAN_OTA_Cmd *cmd)
{
    LOGI("Received block start command\r\n");
    if(!can_ota_ctx.is_updating) {
        LOGE("Not in update mode!\r\n");
        CAN_OTA_SendResponse(cmd->seq, CAN_OTA_RESP_ERROR);
        return;
    }
    
    // 获取数据块大小和包数量
    block_transfer.block_size = (cmd->param & 0xFFFF);
    block_transfer.packet_count = ((cmd->param >> 16) & 0xFFFF);
    
    // 验证参数
    if(block_transfer.block_size > MAX_BLOCK_SIZE || 
       block_transfer.packet_count > MAX_PACKETS_PER_BLOCK ||
       block_transfer.packet_count * 8 < block_transfer.block_size) {
        LOGE("Invalid block parameters: size=%d, packets=%d\r\n",
               block_transfer.block_size, block_transfer.packet_count);
        CAN_OTA_SendResponse(cmd->seq, CAN_OTA_RESP_ERROR);
        return;
    }
    
    // 初始化数据块接收
    block_transfer.received_count = 0;
    block_transfer.block_offset = 0;
    block_transfer.is_receiving_block = 1;
    
    LOGI("Starting block transfer: size=%d, packets=%d\r\n",
           block_transfer.block_size, block_transfer.packet_count);
    CAN_OTA_SendResponse(cmd->seq, CAN_OTA_RESP_OK);
}

/**
 * @brief  处理数据块结束命令
 */
static void Handle_Block_End_Command(CAN_OTA_Cmd *cmd)
{
    LOGI("Received block end command\r\n");
    if(!block_transfer.is_receiving_block) {
        LOGE("Not receiving block!\r\n");
        CAN_OTA_SendResponse(cmd->seq, CAN_OTA_RESP_ERROR);
        return;
    }
    
    // 验证接收的数据
    if(block_transfer.received_count != block_transfer.packet_count ||
       block_transfer.block_offset != block_transfer.block_size) {
        LOGE("Block transfer incomplete: received=%d/%d, size=%d/%d\r\n",
               block_transfer.received_count, block_transfer.packet_count,
               block_transfer.block_offset, block_transfer.block_size);
        CAN_OTA_SendResponse(cmd->seq, CAN_OTA_RESP_ERROR);
        return;
    }
    
    // 将数据块写入Flash
    if(OTA_Update(block_transfer.block_buffer, block_transfer.block_size) != OTA_OK) {
        LOGE("Failed to write block to flash %d\r\n", block_transfer.block_size);
        CAN_OTA_SendResponse(cmd->seq, CAN_OTA_RESP_ERROR);
        return;
    }
    
    can_ota_ctx.received_size += block_transfer.block_size;
    
    // 重置数据块传输状态
    block_transfer.is_receiving_block = 0;
    LOGI("Block transfer complete\r\n");
    CAN_OTA_SendResponse(cmd->seq, CAN_OTA_RESP_OK);
}

/**
 * @brief  处理结束命令
 */
static void Handle_End_Command(CAN_OTA_Cmd *cmd)
{
    LOGI("Received OTA end command\r\n");
    
    LOGI("Received size: %d, Total size: %d\r\n", 
           can_ota_ctx.received_size, can_ota_ctx.total_size);
           
    if(can_ota_ctx.received_size == can_ota_ctx.total_size) {
        // 验证固件
        uint32_t crc = OTA_CalculateCRC32(APP_START_ADDR, can_ota_ctx.total_size);
        if(crc == cmd->param) {
            CAN_OTA_SendResponse(0, CAN_OTA_RESP_VERIFY);
            // 清除升级标志
            OTA_ClearUpgradeFlag();
            // 重启系统
            NVIC_SystemReset();
        } else {
            LOGE("CRC verification failed: calculated=0x%08X, expected=0x%08X\r\n", 
                   crc, cmd->param);
            CAN_OTA_SendResponse(0, CAN_OTA_RESP_ERROR);
        }
    } else {
        LOGE("Received OTA end command, but received size does not match total size\r\n");
        CAN_OTA_SendResponse(0, CAN_OTA_RESP_ERROR);
    }
    can_ota_ctx.is_updating = 0;
}

/**
 * @brief  处理数据帧
 */
static void Handle_Data_Frame(uint8_t *data, uint8_t len)
{
    if(!block_transfer.is_receiving_block) {
        LOGI("Not in block receiving mode!\r\n");
        return;
    }
    
    // 计算本次需要拷贝的实际长度
    uint16_t copy_len = len;
    uint16_t remaining = block_transfer.block_size - block_transfer.block_offset;
    if(copy_len > remaining) {
        copy_len = remaining;  // 最后一包可能只需要部分数据
    }
    
    // 拷贝数据到数据块缓冲区
    memcpy(&block_transfer.block_buffer[block_transfer.block_offset], 
           data, copy_len);
    block_transfer.block_offset += copy_len;
    block_transfer.received_count++;
    
    LOGI("Block transfer progress: %d/%d packets, %d/%d bytes\r\n",
           block_transfer.received_count, block_transfer.packet_count,
           block_transfer.block_offset, block_transfer.block_size);
}

/**
 * @brief  处理CAN OTA消息
 */
void CAN_OTA_HandleMessage(uint32_t id, uint8_t *data, uint8_t len)
{
    // 获取消息类型和目标ID
    uint16_t base_id = id & 0xFF0;  // 获取基础ID (0x400, 0x500, 0x600)
    uint8_t target_id = (id & 0x0F);  // 获取目标设备ID
    
    LOGI("Received message: base_id=0x%03X, target_id=%d, CAN_OTA_CMD_ID=0x%03X\r\n", 
           base_id, target_id, CAN_OTA_CMD_ID);
    
    // 检查是否是发给本设备的消息
    if (target_id != can_ota_ctx.device_id && target_id != 0) {  // 0为广播ID
        LOGW("Not for this device %d\r\n", target_id);
        return;
    }
    
    // 处理命令帧
    if(base_id == CAN_OTA_CMD_ID) {  // 0x400: 命令帧
        LOGI("Processing command frame\r\n");
        CAN_OTA_Cmd *cmd = (CAN_OTA_Cmd*)data;
        LOGI("Processing OTA command: cmd=0x%02X, seq=%d\r\n", cmd->cmd, cmd->seq);
        
        switch(cmd->cmd) {
            case CAN_OTA_CMD_START:
                Handle_Start_Command(cmd);
                break;
                
            case CAN_OTA_CMD_BLOCK_START:
                Handle_Block_Start_Command(cmd);
                break;
                
            case CAN_OTA_CMD_BLOCK_END:
                Handle_Block_End_Command(cmd);
                break;
                
            case CAN_OTA_CMD_END:
                Handle_End_Command(cmd);
                break;
                
            case CAN_OTA_CMD_ABORT:
                LOGI("Received OTA abort command\r\n");
                can_ota_ctx.is_updating = 0;
                CAN_OTA_SendResponse(0, CAN_OTA_RESP_OK);
                break;
                
            default:
                LOGW("Unknown command: 0x%02X\r\n", cmd->cmd);
                // CAN_OTA_SendResponse(0, CAN_OTA_RESP_ERROR);
                break;
        }
    }
    // 处理数据帧
    else if(base_id == CAN_OTA_DATA_ID) {  // 0x600: 数据帧
        LOGI("Processing data frame\r\n");
        // 检查是否是发给本设备的数据帧
        if(target_id != can_ota_ctx.device_id) {
            LOGW("Data frame not for this device %d\r\n", target_id);
            return;
        }
        
        if(!can_ota_ctx.is_updating) {
            LOGW("Not in update mode!\r\n");
            return;
        }
        
        LOGI("Received OTA data frame for device %d\r\n", target_id);
        Handle_Data_Frame(data, len);
    }
    else {
        LOGW("Unknown message type: base_id=0x%03X (expected 0x%03X or 0x%03X)\r\n", 
               base_id, CAN_OTA_CMD_ID, CAN_OTA_DATA_ID);
    }
}

/**
 * @brief  初始化CAN OTA
 */
void CAN_OTA_Init(CAN_OTA_Config *config)
{
    // 保存配置
    can_ota_ctx.device_id = config->device_id;
    can_ota_ctx.group_id = config->group_id;
    can_ota_ctx.is_master = config->is_master;
    
    // // 注册CAN接收回调函数
    // BSP_CAN_RegisterCallback(CAN_OTA_HandleMessage);
    
    LOGI("CAN OTA Init, Device ID: %d, Group ID: %d\r\n", 
           can_ota_ctx.device_id, can_ota_ctx.group_id);
} 